home *** CD-ROM | disk | FTP | other *** search
- """
- Displaying image files in a separate thread on Tk+thread, w/ xv in
- forked & execv'ed processes otherwise.
-
- view(array): will spawn a displaying program for arrays which are
- either NxM or NxMx3. does the 'min/max' and conversion
- to char.
-
- array2ppm(array): given an NxM or NxMx3 array, returns a ppm string
- which is a valid thing to put in a PPM file. (or
- PGM file if NxM file).
-
- TODO:
- - automatic scaling for small images
- - accept rank-1 arrays
-
- NOTE: This is a modified version which removes all threading and PIL
- support. It should work on any system with Tkinter alone.
-
- """
-
- DEFAULT_HEIGHT = 255
- MINSIZE = 150
-
- import os
- import Tkinter
- from Numeric import *
- import tempfile, time
-
-
- def save_ppm(ppm, fname=None):
- if fname == None:
- fname = tempfile.mktemp('.ppm')
- f = open(fname, 'wb')
- f.write(ppm)
- f.close()
- return fname
-
-
- def array2ppm(image):
- # scaling
- if len(image.shape) == 2:
- # B&W:
- image = transpose(image)
- return "P5\n#PPM version of array\n%d %d\n255\n%s" % \
- (image.shape[1], image.shape[0], ravel(image).tostring())
- else:
- # color
- image = transpose(image, (1, 0, 2))
- return "P6\n%d %d\n255\n%s" % \
- (image.shape[1], image.shape[0], ravel(image).tostring())
-
- def preprocess(image, (scalex,scaley)):
- assert len(image.shape) in (1, 2) or \
- len(image.shape) == 3 and image.shape[2] == 3, \
- "image not correct format"
- themin = float(minimum.reduce(ravel(image)))
- themax = float(maximum.reduce(ravel(image)))
- if len(image.shape) == 1:
- len_x = image.shape[0]
- ys = ((image - themin)/(themax-themin)*(DEFAULT_HEIGHT-1)).astype('b')
- image = (zeros((DEFAULT_HEIGHT, len_x))+255).astype('b')
- for x in range(len_x):
- image[DEFAULT_HEIGHT-1-ys[x],len_x-x-1] = 0
- image = transpose(image)
- elif image.typecode() != 'b':
- image = (image - themin) / (themax-themin) * 255
- image = image.astype('b')
-
- len_x, len_y = image.shape[:2]
- if scalex is None:
- if len_x < MINSIZE:
- scalex = int(float(MINSIZE) / len_x) + 1
- else:
- scalex = 1
- if scaley is None:
- if len_y < MINSIZE:
- scaley = int(float(MINSIZE) / len_y) + 1
- else:
- scaley = 1
- return image, (scalex, scaley)
-
-
- class PPMImage(Tkinter.Label):
- def __init__(self, master, ppm, (scalex, scaley)):
- self.image = Tkinter.PhotoImage(file=save_ppm(ppm))
- w, h = self.image.width(), self.image.height()
- self.image = self.image.zoom(scalex, scaley)
- self.image.configure(width=w*scalex, height=h*scaley)
- Tkinter.Label.__init__(self, master, image=self.image,
- bg="black", bd=0)
-
- self.pack()
-
- # Start the Tk process from which all subsequent windows will be opened.
- def tk_root():
- if Tkinter._default_root is None:
- root = Tkinter.Tk()
- Tkinter._default_root.withdraw()
- else:
- root = Tkinter._default_root
- return root
-
- _root = tk_root()
-
- def view(image, scale=None):
- """Display an image, optionally rescaling it.
-
- scale can be either an integer or a tuple of 2 integers (for separate x/y
- rescaling. """
-
- if scale is None:
- scale=(None,None)
- else:
- try:
- len(scale)
- except TypeError:
- scale = (scale,scale)
-
- image, scales = preprocess(image, scale)
- tl = Tkinter.Toplevel()
- u = PPMImage(tl, array2ppm(image), scales)
- u.pack(fill='both', expand=1)
- u.tkraise()
-